Understanding Child Growth & HIV Awareness Worldwide
Author
Lukman Khiruddin
Published
April 22, 2025
Introduction
In every corner of our world, the journey of childhood unfolds with both promise and pitfalls. Where the glow of hope is often shadowed by the realities of stunted growth and the silent spread of HIV.
This dashboard invites you to explore the global landscape of child development, weaving together vivid data on child stunting and HIV awareness to reveal the stark contrasts and hidden connections shaping young lives.
Show code
# Import necessary librariesimport pandas as pdimport numpy as npimport plotly.express as pximport plotly.graph_objects as gofrom plotly.subplots import make_subplotsimport geopandas as gpdimport json# Define color scheme to match R's ggplot2COLORS = {'green': '#00BA38','red': '#F8766D','blue': '#619CFF','orange': '#FF9E4A','yellow': '#B79F00','background': '#F0F0F0','grid': '#CCCCCC','text': '#000000'}
HIV Knowledge Among Youth by Country
This comparison highlights the percentage of young people (aged 15–24) who possess comprehensive, correct knowledge of HIV across countries. By displaying both the leaders and laggards, we can better understand the global disparities in HIV education. This helps policymakers identify both success stories to emulate and areas where urgent action is needed.
# Filter HIV knowledge datahiv_knowledge_data = combined_indicators[ combined_indicators['indicator'].str.contains('comprehensive, correct knowledge of HIV', case=False, na=False)]hiv_knowledge_data = hiv_knowledge_data[~hiv_knowledge_data['obs_value'].isna()]# Get the most recent data for each country and sexrecent_hiv_knowledge = hiv_knowledge_data.sort_values('time_period', ascending=False).groupby(['country', 'sex']).first().reset_index()# Calculate average knowledge by country and sortavg_knowledge = recent_hiv_knowledge.groupby('country')['obs_value'].mean().reset_index()avg_knowledge = avg_knowledge.sort_values('obs_value', ascending=True) # Ascending for horizontal bars# Get top 5 countriestop_5_countries = avg_knowledge.tail(5) # Using tail because we reversed the order# Create interactive bar chartfig = go.Figure()fig.add_trace(go.Bar( x=top_5_countries['obs_value'], y=top_5_countries['country'], orientation='h', marker_color=COLORS['green'], text=top_5_countries['obs_value'].round(1).astype(str) +'%', textposition='outside', hovertemplate='<b>%{y}</b><br>HIV Knowledge: %{x:.1f}%<extra></extra>', hoverlabel=dict( bgcolor='white', font_size=12, font_family='Arial' )))fig.update_layout( title={'text': 'Top 5 Countries with Highest HIV Knowledge<br><sup>Youth (15-24 years)</sup>','x': 0.5,'xanchor': 'center' }, xaxis_title='Percentage (%)', yaxis_title=None, xaxis=dict(range=[0, 75]), plot_bgcolor='white', showlegend=False, height=400,)fig.update_xaxes(gridcolor=COLORS['grid'], zeroline=False)fig.update_yaxes(gridcolor='white')fig.show()
Show code for bottom countries chart
# Get bottom 5 countriesbottom_5_countries = avg_knowledge.head(5)# Create interactive bar chartfig = go.Figure()fig.add_trace(go.Bar( x=bottom_5_countries['obs_value'], y=bottom_5_countries['country'], orientation='h', marker_color=COLORS['green'], text=bottom_5_countries['obs_value'].round(1).astype(str) +'%', textposition='outside', hovertemplate='<b>%{y}</b><br>HIV Knowledge: %{x:.1f}%<extra></extra>', hoverlabel=dict( bgcolor='white', font_size=12, font_family='Arial' )))fig.update_layout( title={'text': 'Bottom 5 Countries with Lowest HIV Knowledge<br><sup>Youth (15-24 years)</sup>','x': 0.5,'xanchor': 'center' }, xaxis_title='Percentage (%)', yaxis_title=None, xaxis=dict(range=[0, 75]), plot_bgcolor='white', showlegend=False, height=400,)fig.update_xaxes(gridcolor=COLORS['grid'], zeroline=False)fig.update_yaxes(gridcolor='white')fig.show()
This tabbed comparison reveals stark disparities in HIV knowledge among youth globally. The top-performing countries (primarily in Eastern and Southern Africa) have achieved knowledge rates above 50%, while the lowest-performing countries show rates below 5%.
This significant gap (over 55 percentage points between highest and lowest) highlights implementation disparities in HIV education programs worldwide. Countries at the bottom of the ranking could benefit from adapting successful education strategies from top-performing nations.
Top 4 Countries with HIV Knowledge Trends Over Time
This line chart tracks the evolution of HIV knowledge among males and females in 4 countries over time. The visual uncovers whether both genders are benefiting equally from education efforts, and whether progress is steady, stagnant, or declining. It provides a clear picture of gender gaps and helps guide future interventions to ensure no one is left behind.
Show code for trends chart
# Filter data for comprehensive HIV knowledgehiv_knowledge_data = combined_indicators[ combined_indicators['indicator'].str.contains('comprehensive, correct knowledge of HIV', case=False, na=False)]hiv_knowledge_data = hiv_knowledge_data[~hiv_knowledge_data['obs_value'].isna()]hiv_knowledge_data = hiv_knowledge_data[hiv_knowledge_data['sex'].isin(['Female', 'Male'])]# Count data points by country and sex to find those with the most datacountry_data_counts = ( hiv_knowledge_data.groupby(['country', 'sex']) .size() .reset_index(name='data_points') .groupby('country') .agg( total_points=('data_points', 'sum'), has_both_sexes=('sex', 'nunique') ) .reset_index())# Filter for countries with both sexes and sort by total data pointscountry_data_counts = country_data_counts[country_data_counts['has_both_sexes'] >1]country_data_counts = country_data_counts.sort_values('total_points', ascending=False)# Get top 4 countries with most data pointstop_trend_countries = country_data_counts.head(4)['country'].tolist()# Filter data for top countriestrend_data = hiv_knowledge_data[hiv_knowledge_data['country'].isin(top_trend_countries)]# Create subplots with more vertical spacefig = make_subplots( rows=2, cols=2, subplot_titles=top_trend_countries, vertical_spacing=0.2, # Increase vertical spacing between plots horizontal_spacing=0.15# Increase horizontal spacing between plots)# Plot each countryfor i, country inenumerate(top_trend_countries): row = i //2+1 col = i %2+1 country_data = trend_data[trend_data['country'] == country]for sex, color inzip(['Female', 'Male'], [COLORS['red'], COLORS['blue']]): sex_data = country_data[country_data['sex'] == sex] fig.add_trace( go.Scatter( x=sex_data['time_period'], y=sex_data['obs_value'], name=sex, line=dict(color=color), mode='lines+markers', showlegend=(i ==0), # Show legend only for first country hovertemplate='Year: %{x}<br>'+ sex +': %{y:.1f}%<extra></extra>' ), row=row, col=col )fig.update_layout( title={'text': 'HIV Knowledge Trends by Sex & Country<br><sup>Percentage of youth (15-24) with comprehensive knowledge</sup>','x': 0.5,'xanchor': 'center','y': 0.95, # Move main title up slightly'yanchor': 'top' }, height=800, # Increase overall height showlegend=True, legend=dict( orientation="h", yanchor="bottom", y=-0.15, xanchor="center", x=0.5 ), plot_bgcolor='white')# Update all axesfor i inrange(1, 5): row = (i-1)//2+1 col = (i-1)%2+1# Update y-axes fig.update_yaxes( title_text='%', range=[0, 60], row=row, col=col, gridcolor=COLORS['grid'], zeroline=False )# Update x-axes fig.update_xaxes( title_text='Year', row=row, col=col, gridcolor=COLORS['grid'], zeroline=False )# Update subplot titles font and positionfor i in fig['layout']['annotations']: i['font'] =dict(size=12, color='black') i['y'] = i['y'] +0.03# Move subplot titles up slightlyfig.show()
This line chart reveals the evolution of HIV knowledge among young people across countries with the richest trend data, showing patterns of change over time for both males and females.
Global Gender Gap in HIV Knowledge
This scatterplot displays HIV knowledge levels for young people (aged 15-24) across all countries, comparing males and females. Each point represents a country-gender combination, with the most recent available data for each country. The visualization reveals a clear pattern of gender disparity in HIV knowledge globally.
Show code for global comparison
# Get the most recent data for each country and sex combinationhiv_knowledge_global = ( hiv_knowledge_data .sort_values('time_period', ascending=False) .groupby(['country', 'sex']) .first() .reset_index())# Filter to just Male and Female datahiv_knowledge_global = hiv_knowledge_global[hiv_knowledge_global['sex'].isin(['Female', 'Male'])]# Create scatter plot with box plotsfig = go.Figure()# Add box plotsfor sex, color inzip(['Female', 'Male'], [COLORS['red'], COLORS['blue']]): sex_data = hiv_knowledge_global[hiv_knowledge_global['sex'] == sex]# Add box plot fig.add_trace(go.Box( x=[sex] *len(sex_data), y=sex_data['obs_value'], name=sex, marker_color=color, boxpoints='all', jitter=0.3, pointpos=-1.8, marker=dict( color=color, size=8, opacity=0.7 ), line=dict(color='black'), fillcolor='white', hovertemplate="Country: %{text}<br>Value: %{y:.1f}%<extra></extra>", text=sex_data['country'] ))# Add horizontal line at medianmedian_value = hiv_knowledge_global['obs_value'].median()fig.add_shape(type='line', x0='Female', x1='Male', y0=median_value, y1=median_value, line=dict( color='darkgray', width=2, dash='dash' ))# Update layoutfig.update_layout( title={'text': 'Global Gender Gap in HIV Knowledge<br><sup>Most recent data on youth (15-24) with comprehensive HIV knowledge by country</sup>','x': 0.5,'xanchor': 'center' }, yaxis_title='HIV Knowledge (%)', xaxis_title=None, yaxis=dict(range=[0, 70]), plot_bgcolor='white', height=600, showlegend=False,)fig.update_yaxes(gridcolor=COLORS['grid'], zeroline=False)fig.show()